package com.hyts.classcode.classload.load;

import com.hyts.classcode.classload.config.ClassloaderConfig;
import com.hyts.jlogger.util.StringUtils;

import javax.tools.JavaFileObject;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;

/**
 * project-name:coffice-toolbox
 * package-name:com.hyts.classloader.load
 * author:Libo/Alex
 * create-date:2019-05-18 13:20
 * copyright:libo-hyts-github
 * email:libo2dev@aliyun.com
 * description:此类主要用于: 系统默认的类型加载器
 */
public class LocalClassLoader extends AbstractClassLoader{


    public LocalClassLoader(ClassLoader classLoader) {
        super(classLoader);
    }


    public LocalClassLoader(String compilePath) {
        super(compilePath, LocalClassLoader.class.getClassLoader());
    }

    @Override
    public Class<?> searchClassObject(String name) {
        //判断是否传值是否为空
        if(StringUtils.isNull(name)){
            throw new NullPointerException("传入的加载class的名称不允许为空!");
        }
        name = name.contains(".")? name.replace(".", File.separator):name;
        byte[] data = new byte[0];
        try {
            data = classFileTransferByteArray(getCompilePath()+name.concat(JavaFileObject.Kind.CLASS.extension));
        } catch (Exception e) {
            e.printStackTrace();
        }
        Class clazz = defineClass(name.replace(File.separator,"."), data, 0, data.length);
        if (null == clazz) {
            //如果在这个类加载器中都不能找到这个类的话，就真的找不到了
        }
        return clazz;
    }

    public Class getClass(String name,byte[] data){
        Class clazz = defineClass(name, data, 0, data.length);
        return clazz;
    }


    @Deprecated
    @Override
    public Class<?> searchClassObjectByPath(String name, String path) {
        throw new UnsupportedOperationException("此方法不支持暂时");
    }


    protected byte[] classFileTransferByteArray(String classFile){
        try (
                FileInputStream fileInputStream = new FileInputStream(classFile);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                FileChannel fileChannel = fileInputStream.getChannel();
                WritableByteChannel writableByteChannel = Channels.newChannel(outputStream);
             ){
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(ClassloaderConfig.DEFAULT_CLASS_READER_MAX_SIZE);
            long value = 0;
            while((value = fileChannel.read(byteBuffer)) > 0){
                byteBuffer.flip();
                writableByteChannel.write(byteBuffer);
                byteBuffer.clear();
            }
            return outputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new byte[0];
    }
}
